Tecnicatura Superior en Ciencia de Datos e Inteligencia Artificial¶

Práctica Profesionalizante I¶

Equipo Data Voyagers:

  • URZAGASTE, María Gisela
  • PERALTA, María Laura
  • LEDEZMA, Mariano
  • BADIN, María Paula

Análisis de la Cadena de Suministro¶

En este proyecto, nos enfocaremos en la cadena de suministro utilizando un dataset extenso que abarca información de ventas y operaciones. El objetivo es explorar, limpiar y analizar los datos para obtener insights valiosos que puedan ayudar a mejorar la eficiencia y efectividad en la gestión de la cadena de suministro.

Exploración inicial y Limpieza de datos¶

En la primera fase del análisis de datos, nos enfocamos en la Exploración Inicial para obtener una visión general del dataset. Esta etapa es fundamental para entender la estructura del conjunto de datos, identificando las características principales, el tipo de datos en cada columna, y revisando una muestra de los registros. Al realizar esta exploración, se busca confirmar que los datos se han cargado correctamente y que las columnas están en el formato adecuado para un análisis más detallado.

La Limpieza de Datos, por otro lado, es crucial para preparar el dataset para el análisis. En esta fase, se abordan problemas como la presencia de valores faltantes, duplicados y errores en los datos. Se identifican y eliminan columnas irrelevantes, se corrigen o imputan valores nulos, y se transforman datos para que sean consistentes y útiles. Esta limpieza asegura que el dataset sea preciso y esté libre de inconsistencias, facilitando así análisis posteriores más robustos y confiables.

Importación de librerías¶

Importamos las librerías y herramientas necesarias para el desarrollo del proyecto. Éstas incluyen:

  • NumPy: Biblioteca para realizar operaciones matemáticas y de álgebra lineal de manera eficiente.
  • Pandas: Herramienta poderosa para la manipulación y análisis de datos, especialmente útil con archivos CSV.
  • Seaborn: Librería para visualización de datos basada en Matplotlib, que facilita la creación de gráficos estadísticos atractivos.
  • Matplotlib.pyplot: Parte de Matplotlib, se utiliza para crear gráficos estáticos y personalizables.
  • Plotly.graph_objs: Módulo de Plotly para construir gráficos complejos e interactivos.
  • Plotly.subplots.make_subplots: Función de Plotly para crear gráficos con múltiples subplots en un solo diseño.
  • Plotly.express: Interfaz simplificada de Plotly para generar gráficos interactivos de manera rápida.
  • Plotly.offline.init_notebook_mode: Activa el uso de gráficos interactivos de Plotly dentro de notebooks como Colab.
  • gdown: Librería utilizada para descargar archivos directamente desde Google Drive
In [35]:
import numpy as np 
import pandas as pd 
import seaborn as sns; sns.set(style="ticks", color_codes=True)
import matplotlib.pyplot as plt
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import seaborn as sns
import plotly.express as px
%matplotlib inline

from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
init_notebook_mode(connected = False)

Cargar el conjunto de datos en el entorno de trabajo

Realizar una revisión general
dataset original

In [ ]:
#Importación de dataset desde github
url = 'https://github.com/ISPC-PP1-2024/proyecto/blob/main/datos/DataCoSupplyChainDataset/DataCoSupplyChainDataset.csv'
df_1 = pd.read_csv(url)
In [61]:
# dataset original -para jupyter
df_1=pd.read_csv('C:\\Users\\Usuario\\Desktop\\2024\\materias\\CDIA\\2semestre\\pp1-cdia23\\ejemplo suply chain\\DataCoSupplyChainDataset.csv\\para jupyter\\SinAcento.csv', encoding='latin1', sep=';',  low_memory=False)
pd.set_option('display.max_rows', 60)    #muestra 60 columnas
pd.set_option('display.max_columns', 100)  # 100 filas
pd.set_option('display.width', 1000)
In [62]:
# detalle
df_1.head()
Out[62]:
Type Days for shipping (real) Days for shipment (scheduled) Benefit per order Sales per customer Delivery Status Late_delivery_risk Category Id Category Name Customer City Customer Country Customer Email Customer Fname Customer Id Customer Lname Customer Password Customer Segment Customer State Customer Street Customer Zipcode Department Id Department Name Latitude Longitude Market Order City Order Country Order Customer Id order date (DateOrders) Order Id Order Item Cardprod Id Order Item Discount Order Item Discount Rate Order Item Id Order Item Product Price Order Item Profit Ratio Order Item Quantity Sales Order Item Total Order Profit Per Order Order Region Order State Order Status Order Zipcode Product Card Id Product Category Id Product Description Product Image Product Name Product Price Product Status shipping date (DateOrders) Shipping Mode
0 DEBIT 3 4 9.125000e+01 3.146400e+09 Advance shipping 0 73 Sporting Goods Caguas Puerto Rico XXXXXXXXX Cally 20755 Holloway XXXXXXXXX Consumer PR 5365 Noble Nectar Island 725.0 2 Fitness 182.514.534 -6.603.705.597 Pacific Asia Bekasi Indonesia 20755 1/31/2018 22:56 77202 1360 1.310.999.966 0.04 180517 327.75 0.289999992 1 327.75 3.146.400.146 91.25 Southeast Asia Java Occidental COMPLETE NaN 1360 73 NaN http://images.acmesports.sports/Smart+watch Smart watch 327.75 0 2/3/2018 22:56 Standard Class
1 TRANSFER 5 4 -2.490900e+09 3.113600e+09 Late delivery 1 73 Sporting Goods Caguas Puerto Rico XXXXXXXXX Irene 19492 Luna XXXXXXXXX Consumer PR 2679 Rustic Loop 725.0 2 Fitness 1.827.945.137 -660.370.636 Pacific Asia Bikaner India 19492 1/13/2018 12:27 75939 1360 1.638.999.939 0.05 179254 327.75 -0.800000012 1 327.75 3.113.599.854 -2.490.899.963 South Asia Rajastán PENDING NaN 1360 73 NaN http://images.acmesports.sports/Smart+watch Smart watch 327.75 0 1/18/2018 12:27 Standard Class
2 CASH 4 4 -2.477800e+09 3.097200e+09 Shipping on time 0 73 Sporting Goods San Jose EE. UU. XXXXXXXXX Gillian 19491 Maldonado XXXXXXXXX Consumer CA 8510 Round Bear Gate 95125.0 2 Fitness 3.729.223.251 -121.881.279 Pacific Asia Bikaner India 19491 1/13/2018 12:06 75938 1360 1.803.000.069 0.06 179253 327.75 -0.800000012 1 327.75 3.097.200.012 -2.477.799.988 South Asia Rajastán CLOSED NaN 1360 73 NaN http://images.acmesports.sports/Smart+watch Smart watch 327.75 0 1/17/2018 12:06 Standard Class
3 DEBIT 3 4 2.286000e+09 3.048100e+09 Advance shipping 0 73 Sporting Goods Los Angeles EE. UU. XXXXXXXXX Tana 19490 Tate XXXXXXXXX Home Office CA 3200 Amber Bend 90027.0 2 Fitness 3.412.594.605 -1.182.910.156 Pacific Asia Townsville Australia 19490 1/13/2018 11:45 75937 1360 2.294.000.053 0.07 179252 327.75 0.079999998 1 327.75 3.048.099.976 2.286.000.061 Oceania Queensland COMPLETE NaN 1360 73 NaN http://images.acmesports.sports/Smart+watch Smart watch 327.75 0 1/16/2018 11:45 Standard Class
4 PAYMENT 2 4 1.342100e+09 2.982500e+02 Advance shipping 0 73 Sporting Goods Caguas Puerto Rico XXXXXXXXX Orli 19489 Hendricks XXXXXXXXX Corporate PR 8671 Iron Anchor Corners 725.0 2 Fitness 1.825.376.892 -6.603.704.834 Pacific Asia Townsville Australia 19489 1/13/2018 11:24 75936 1360 29.5 0.09 179251 327.75 0.449999988 1 327.75 298.25 1.342.100.067 Oceania Queensland PENDING_PAYMENT NaN 1360 73 NaN http://images.acmesports.sports/Smart+watch Smart watch 327.75 0 1/15/2018 11:24 Standard Class
In [63]:
# tamaño en filas y columnas del dataset original
df_1.shape
Out[63]:
(180519, 53)
In [64]:
# trabajo previo
# 1- filtrar el set de datos original por pais para abarcar solo argentina, brasil y mexico
# 2- quitar columnas

#EL DATAFRAME RESULTANTE DE ESTE PROCESO SE EMPLEA PARA TRABAJAR

Operaciones sobr el conjunto de datos
Se realiza un filtrado sobre el dataset original para incluir solo los paises: Argentina, Brasil y Mexico

In [65]:
df = df_1[df_1['Order Country'].isin(['Argentina', 'Brasil', 'Mexico'])]
In [66]:
#Mostrar los primeras filas del dataframe resultante
df.head()
Out[66]:
Type Days for shipping (real) Days for shipment (scheduled) Benefit per order Sales per customer Delivery Status Late_delivery_risk Category Id Category Name Customer City Customer Country Customer Email Customer Fname Customer Id Customer Lname Customer Password Customer Segment Customer State Customer Street Customer Zipcode Department Id Department Name Latitude Longitude Market Order City Order Country Order Customer Id order date (DateOrders) Order Id Order Item Cardprod Id Order Item Discount Order Item Discount Rate Order Item Id Order Item Product Price Order Item Profit Ratio Order Item Quantity Sales Order Item Total Order Profit Per Order Order Region Order State Order Status Order Zipcode Product Card Id Product Category Id Product Description Product Image Product Name Product Price Product Status shipping date (DateOrders) Shipping Mode
84 PAYMENT 4 2 2.347000e+09 144.0 Late delivery 1 24 Women's Apparel Caguas Puerto Rico XXXXXXXXX Mary 8541 Smith XXXXXXXXX Home Office PR 5700 Little Circle 725.0 5 Golf 1.829.609.299 -6.637.050.629 LATAM Juazeiro Brasil 8541 4/11/2017 15:49 56973 502 6 0.04 142502 50 0.159999996 3 150 144 2.346.999.931 South America Bahía PENDING_PAYMENT NaN 502 24 NaN http://images.acmesports.sports/Nike+Men%27s+D... Nike Men's Dri-FIT Victory Golf Polo 50 0 4/15/2017 15:49 Second Class
86 PAYMENT 6 2 4.366000e+09 139.5 Late delivery 1 24 Women's Apparel Caguas Puerto Rico XXXXXXXXX Mary 3752 Vega XXXXXXXXX Home Office PR 7840 Umber Sky Villas 725.0 5 Golf 182.105.732 -6.637.058.258 LATAM Mexico City Mexico 3752 3/16/2017 2:54 55155 502 10.5 0.07 137932 50 0.310000002 3 150 139.5 4.365.999.985 Central America Distrito Federal PENDING_PAYMENT NaN 502 24 NaN http://images.acmesports.sports/Nike+Men%27s+D... Nike Men's Dri-FIT Victory Golf Polo 50 0 3/22/2017 2:54 Second Class
87 PAYMENT 2 2 1.320000e+09 132.0 Shipping on time 0 24 Women's Apparel Caguas Puerto Rico XXXXXXXXX Wayne 4673 Hodges XXXXXXXXX Home Office PR 7509 Iron Concession 725.0 5 Golf 1.820.111.656 -6.637.059.021 LATAM Tlaquepaque Mexico 4673 3/29/2015 10:33 5991 502 18 0.12 14921 50 0.100000001 3 150 132 1.319.999.981 Central America Jalisco PENDING_PAYMENT NaN 502 24 NaN http://images.acmesports.sports/Nike+Men%27s+D... Nike Men's Dri-FIT Victory Golf Polo 50 0 3/31/2015 10:33 Second Class
88 PAYMENT 4 2 4.620000e+09 132.0 Late delivery 1 24 Women's Apparel Caguas Puerto Rico XXXXXXXXX Mary 5367 Mccormick XXXXXXXXX Home Office PR 2199 Silver Autumn Key 725.0 5 Golf 1.821.469.116 -6.637.051.392 LATAM Puebla Mexico 5367 2/3/2015 00:28 2263 502 18 0.12 5671 50 0.349999994 3 150 132 4.620.000.076 Central America Puebla PENDING_PAYMENT NaN 502 24 NaN http://images.acmesports.sports/Nike+Men%27s+D... Nike Men's Dri-FIT Victory Golf Polo 50 0 2/7/2015 00:28 Second Class
89 PAYMENT 4 2 1.044000e+09 130.5 Late delivery 1 24 Women's Apparel Caguas Puerto Rico XXXXXXXXX Mary 5367 Mccormick XXXXXXXXX Home Office PR 2199 Silver Autumn Key 725.0 5 Golf 1.821.469.116 -6.637.051.392 LATAM Puebla Mexico 5367 2/3/2015 00:28 2263 502 19.5 0.13 5669 50 0.079999998 3 150 130.5 1.043.999.958 Central America Puebla PENDING_PAYMENT NaN 502 24 NaN http://images.acmesports.sports/Nike+Men%27s+D... Nike Men's Dri-FIT Victory Golf Polo 50 0 2/7/2015 00:28 Second Class
In [67]:
#Mostrar las ultimas filas del dataframe resultante
df.tail()
Out[67]:
Type Days for shipping (real) Days for shipment (scheduled) Benefit per order Sales per customer Delivery Status Late_delivery_risk Category Id Category Name Customer City Customer Country Customer Email Customer Fname Customer Id Customer Lname Customer Password Customer Segment Customer State Customer Street Customer Zipcode Department Id Department Name Latitude Longitude Market Order City Order Country Order Customer Id order date (DateOrders) Order Id Order Item Cardprod Id Order Item Discount Order Item Discount Rate Order Item Id Order Item Product Price Order Item Profit Ratio Order Item Quantity Sales Order Item Total Order Profit Per Order Order Region Order State Order Status Order Zipcode Product Card Id Product Category Id Product Description Product Image Product Name Product Price Product Status shipping date (DateOrders) Shipping Mode
179618 TRANSFER 6 4 1.337500e+02 2.729500e+09 Late delivery 1 17 Cleats Caguas Puerto Rico XXXXXXXXX Brenda 12354 Wells XXXXXXXXX Consumer PR 3762 Amber Estates 725.0 4 Apparel 1.823.072.052 -6.637.063.599 LATAM Goiânia Brasil 12354 4/18/2015 13:41 7370 365 27 0.09 18457 5.999.000.168 0.49000001 5 2.999.500.122 2.729.500.122 133.75 South America Goiás PENDING NaN 365 17 NaN http://images.acmesports.sports/Perfect+Fitnes... Perfect Fitness Perfect Rip Deck 5.999.000.168 0 4/24/2015 13:41 Standard Class
179621 TRANSFER 3 4 -2.610000e+09 2.609600e+09 Advance shipping 0 17 Cleats Juana Diaz Puerto Rico XXXXXXXXX Mary 10344 Smith XXXXXXXXX Consumer PR 2839 Grand Timber Canyon 795.0 4 Apparel 1.805.199.051 -6.650.184.631 LATAM Villahermosa Mexico 10344 5/16/2017 21:33 59387 365 3.899.000.168 0.13 148676 5.999.000.168 -0.100000001 5 2.999.500.122 2.609.599.915 -2.610.000.038 Central America Tabasco PENDING NaN 365 17 NaN http://images.acmesports.sports/Perfect+Fitnes... Perfect Fitness Perfect Rip Deck 5.999.000.168 0 5/19/2017 21:33 Standard Class
179623 TRANSFER 2 4 1.174300e+09 2.609600e+09 Advance shipping 0 17 Cleats Caguas Puerto Rico XXXXXXXXX Mary 8917 Smith XXXXXXXXX Consumer PR 4992 Jagged Forest Subdivision 725.0 4 Apparel 1.822.487.068 -6.637.052.155 LATAM Barueri Brasil 8917 4/13/2017 14:25 57106 365 3.899.000.168 0.13 142839 5.999.000.168 0.449999988 5 2.999.500.122 2.609.599.915 1.174.300.003 South America São Paulo PENDING NaN 365 17 NaN http://images.acmesports.sports/Perfect+Fitnes... Perfect Fitness Perfect Rip Deck 5.999.000.168 0 4/15/2017 14:25 Standard Class
179624 TRANSFER 3 4 4.844000e+09 2.549600e+09 Advance shipping 0 17 Cleats Caguas Puerto Rico XXXXXXXXX Mary 9204 Harris XXXXXXXXX Consumer PR 8713 Quaking Abbey 725.0 4 Apparel 1.828.453.636 -6.637.060.547 LATAM Maceió Brasil 9204 5/27/2017 16:48 60127 365 4.499.000.168 0.15 150462 5.999.000.168 0.189999998 5 2.999.500.122 2.549.600.067 4.843.999.863 South America Alagoas PENDING NaN 365 17 NaN http://images.acmesports.sports/Perfect+Fitnes... Perfect Fitness Perfect Rip Deck 5.999.000.168 0 5/30/2017 16:48 Standard Class
179628 TRANSFER 3 4 6.749000e+09 2.249600e+09 Advance shipping 0 17 Cleats Caguas Puerto Rico XXXXXXXXX Jerry 7024 Smith XXXXXXXXX Consumer PR 5149 Rocky Pine Moor 725.0 4 Apparel 1.822.907.066 -6.637.058.258 LATAM Mexico City Mexico 7024 5/19/2017 3:51 59542 365 7.498.999.786 0.25 149029 5.999.000.168 0.300000012 5 2.999.500.122 2.249.600.067 6.748.999.786 Central America Distrito Federal PENDING NaN 365 17 NaN http://images.acmesports.sports/Perfect+Fitnes... Perfect Fitness Perfect Rip Deck 5.999.000.168 0 5/22/2017 3:51 Standard Class
In [68]:
#Nuevo tamaño del dataframe
df.shape
Out[68]:
(23090, 53)

Información general del DataFrame ---tipo de datos---

In [69]:
df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 23090 entries, 84 to 179628
Data columns (total 53 columns):
 #   Column                         Non-Null Count  Dtype  
---  ------                         --------------  -----  
 0   Type                           23090 non-null  object 
 1   Days for shipping (real)       23090 non-null  int64  
 2   Days for shipment (scheduled)  23090 non-null  int64  
 3   Benefit per order              23090 non-null  float64
 4   Sales per customer             23090 non-null  float64
 5   Delivery Status                23090 non-null  object 
 6   Late_delivery_risk             23090 non-null  int64  
 7   Category Id                    23090 non-null  int64  
 8   Category Name                  23090 non-null  object 
 9   Customer City                  23090 non-null  object 
 10  Customer Country               23090 non-null  object 
 11  Customer Email                 23090 non-null  object 
 12  Customer Fname                 23090 non-null  object 
 13  Customer Id                    23090 non-null  int64  
 14  Customer Lname                 23090 non-null  object 
 15  Customer Password              23090 non-null  object 
 16  Customer Segment               23090 non-null  object 
 17  Customer State                 23090 non-null  object 
 18  Customer Street                23090 non-null  object 
 19  Customer Zipcode               23090 non-null  float64
 20  Department Id                  23090 non-null  int64  
 21  Department Name                23090 non-null  object 
 22  Latitude                       23090 non-null  object 
 23  Longitude                      23090 non-null  object 
 24  Market                         23090 non-null  object 
 25  Order City                     23090 non-null  object 
 26  Order Country                  23090 non-null  object 
 27  Order Customer Id              23090 non-null  int64  
 28  order date (DateOrders)        23090 non-null  object 
 29  Order Id                       23090 non-null  int64  
 30  Order Item Cardprod Id         23090 non-null  int64  
 31  Order Item Discount            23090 non-null  object 
 32  Order Item Discount Rate       23090 non-null  float64
 33  Order Item Id                  23090 non-null  int64  
 34  Order Item Product Price       23090 non-null  object 
 35  Order Item Profit Ratio        23090 non-null  object 
 36  Order Item Quantity            23090 non-null  int64  
 37  Sales                          23090 non-null  object 
 38  Order Item Total               23090 non-null  object 
 39  Order Profit Per Order         23090 non-null  object 
 40  Order Region                   23090 non-null  object 
 41  Order State                    23090 non-null  object 
 42  Order Status                   23090 non-null  object 
 43  Order Zipcode                  0 non-null      float64
 44  Product Card Id                23090 non-null  int64  
 45  Product Category Id            23090 non-null  int64  
 46  Product Description            0 non-null      float64
 47  Product Image                  23090 non-null  object 
 48  Product Name                   23090 non-null  object 
 49  Product Price                  23090 non-null  object 
 50  Product Status                 23090 non-null  int64  
 51  shipping date (DateOrders)     23090 non-null  object 
 52  Shipping Mode                  23090 non-null  object 
dtypes: float64(6), int64(14), object(33)
memory usage: 9.5+ MB

Consideraciones:
1-La informacion general indica que los datos en las columnas del tipo "object", significa que son un cadena de texto u otro tipo no numerico
2-"product description" y "Order Zipcode" esta en blanco toda la columna "Product state" es "0" para toda la columna

Verificar si existen filas duplicadas o espacios vacios.

In [70]:
# verificar filas duplicadas
duplicados=df[df.duplicated()]
if duplicados.empty:
    print("No hay filas duplicadas en el DataFrame.")
else:
    print("Las siguientes filas están duplicadas:")
    print(duplicados)
No hay filas duplicadas en el DataFrame.
In [71]:
# verificar espacios vacios
hay_vacios = df.isna().any().any()

if hay_vacios:
    print("El DataFrame contiene valores vacíos.")
else:
    print("El DataFrame no contiene valores vacíos.")
El DataFrame contiene valores vacíos.
In [72]:
import pandas as pd
import numpy as np

def check_negative_values(df_1, columns):
    """
    Verifica valores negativos en las columnas especificadas del DataFrame,
    manejando valores no numéricos y nulos.

    Args:
    df (pandas.DataFrame): El DataFrame a verificar
    columns (list): Lista de nombres de columnas a verificar

    Returns:
    dict: Un diccionario con los resultados de la verificación
    """
    results = {}
    for col in columns:
        if col not in df_1.columns:
            results[col] = f"La columna '{col}' no existe en el DataFrame"
            continue
        
        # Convertir la columna a numérica, coerciendo errores a NaN
        numeric_col = pd.to_numeric(df_1[col], errors='coerce')
        
        # Contar valores negativos, excluyendo NaN
        negative_count = (numeric_col < 0).sum()
        nan_count = numeric_col.isna().sum()
        
        if negative_count > 0:
            results[col] = f"Se encontraron {negative_count} valores negativos en '{col}'"
        else:
            results[col] = f"No se encontraron valores negativos en '{col}'"
        
        if nan_count > 0:
            results[col] += f". Además, hay {nan_count} valores no numéricos o nulos"

    return results

# Uso de la función
columns_to_check = ['Order Item Quantity', 'Sales', 'Order Item Total', 'Product Price']
results = check_negative_values(df_1, columns_to_check)

# Imprimir resultados
for col, result in results.items():
    print(result)

# Información adicional sobre tipos de datos
print("\nTipos de datos de las columnas:")
for col in columns_to_check:
    if col in df_1.columns:
        print(f"{col}: {df_1[col].dtype}")
    else:
        print(f"{col}: Columna no encontrada")

       
No se encontraron valores negativos en 'Order Item Quantity'
No se encontraron valores negativos en 'Sales'. Además, hay 155013 valores no numéricos o nulos
No se encontraron valores negativos en 'Order Item Total'. Además, hay 156939 valores no numéricos o nulos
No se encontraron valores negativos en 'Product Price'. Además, hay 155025 valores no numéricos o nulos

Tipos de datos de las columnas:
Order Item Quantity: int64
Sales: object
Order Item Total: object
Product Price: object

De acuerdo a la informacion anterior, luego deberemos tratar las columnas precio y ventas

In [73]:
# Cantidad de valores nulos por columna
missing_data = df.isna().sum()
print(missing_data[missing_data > 0])
Order Zipcode          23090
Product Description    23090
dtype: int64
In [74]:
# quitar columnas vacias 
df = df.drop(['Product Description', 'Order Zipcode', 'Product Status'], axis=1)
In [75]:
#ELIMINAMOS FILAS DEL DATAFRAME QUE NO USAMOS.
columnas_a_eliminar = ['Sales per customer','Category Id','Customer City','Customer Email','Customer Fname','Customer Lname',
'Customer Password','Customer State','Customer Street','Customer Zipcode','Department Id','Department Name','Latitude',
'Longitude','Market','Order City','Order Customer Id','Order Item Cardprod Id','Order Item Discount', 'Order Item Discount Rate',
'Order Item Profit Ratio','Product Image']

df = df.drop(columns=columnas_a_eliminar)

nombres de columnas

In [76]:
df.columns
Out[76]:
Index(['Type', 'Days for shipping (real)', 'Days for shipment (scheduled)', 'Benefit per order', 'Delivery Status', 'Late_delivery_risk', 'Category Name', 'Customer Country', 'Customer Id', 'Customer Segment', 'Order Country', 'order date (DateOrders)', 'Order Id', 'Order Item Id', 'Order Item Product Price', 'Order Item Quantity', 'Sales', 'Order Item Total', 'Order Profit Per Order', 'Order Region', 'Order State', 'Order Status', 'Product Card Id', 'Product Category Id', 'Product Name', 'Product Price', 'shipping date (DateOrders)', 'Shipping Mode'], dtype='object')
In [77]:
#CAMBIAR LAS COLUMNAS A ESPAÑOL
#// prueba para cambiar los valores de las columnas a español
df_espanol=df
In [78]:
#renombro la columna porque tiene espacios
df_espanol.rename(columns={'Category Name':'Categoria',
                           'Type':'Pago'
                           ,'Days for shipping (real)':'DiasEnvio(Real)'
                           , 'Days for shipment (scheduled)':'DiasEnvio(Programado)'
                           , 'Benefit per order':'BeneficioPorPedido'
                           , 'Delivery Status':'EstadoEntrega'
                           , 'Late_delivery_risk':'RiesgoEntregaTardia'
                           , 'Category Name':'Categoria'
                           , 'Customer Country':'PaisCliente'
                           , 'Customer Id':'IDCliente'
                           , 'Customer Segment':'SegmentoCliente'
                           , 'Order Country':'PaisPedido'
                           , 'order date (DateOrders)':'FechaPedido'
                           , 'Order Id':'IDPedido'
                           , 'Order Item Id':'IDArticuloPedido'
                           , 'Order Item Product Price':'PrecioArticuloPedido'
                           , 'Order Item Quantity':'CantidadArticulosPedido'
                           , 'Sales':'Ventas'
                           , 'Order Item Total':'TotalArticulosPedido'
                           , 'Order Profit Per Order':'GananciaPorPedido'
                           , 'Order Region':'RegionPedido'
                           , 'Order State':'DestinoPedido'
                           , 'Order Status':'EstadoPedido'
                           , 'Product Card Id':'IDProducto'
                           , 'Product Category Id':'CategoriaProducto'
                           , 'Product Name':'NombreProducto'
                           , 'Product Price':'PrecioProducto'
                           , 'shipping date (DateOrders)':'FechaEnvio'
                           , 'Shipping Mode':'ModoEnvio'                                
                          
                          },inplace=True)
In [79]:
# Columnas traducidas
df_espanol.info()
<class 'pandas.core.frame.DataFrame'>
Index: 23090 entries, 84 to 179628
Data columns (total 28 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Pago                     23090 non-null  object 
 1   DiasEnvio(Real)          23090 non-null  int64  
 2   DiasEnvio(Programado)    23090 non-null  int64  
 3   BeneficioPorPedido       23090 non-null  float64
 4   EstadoEntrega            23090 non-null  object 
 5   RiesgoEntregaTardia      23090 non-null  int64  
 6   Categoria                23090 non-null  object 
 7   PaisCliente              23090 non-null  object 
 8   IDCliente                23090 non-null  int64  
 9   SegmentoCliente          23090 non-null  object 
 10  PaisPedido               23090 non-null  object 
 11  FechaPedido              23090 non-null  object 
 12  IDPedido                 23090 non-null  int64  
 13  IDArticuloPedido         23090 non-null  int64  
 14  PrecioArticuloPedido     23090 non-null  object 
 15  CantidadArticulosPedido  23090 non-null  int64  
 16  Ventas                   23090 non-null  object 
 17  TotalArticulosPedido     23090 non-null  object 
 18  GananciaPorPedido        23090 non-null  object 
 19  RegionPedido             23090 non-null  object 
 20  DestinoPedido            23090 non-null  object 
 21  EstadoPedido             23090 non-null  object 
 22  IDProducto               23090 non-null  int64  
 23  CategoriaProducto        23090 non-null  int64  
 24  NombreProducto           23090 non-null  object 
 25  PrecioProducto           23090 non-null  object 
 26  FechaEnvio               23090 non-null  object 
 27  ModoEnvio                23090 non-null  object 
dtypes: float64(1), int64(9), object(18)
memory usage: 5.1+ MB
In [80]:
#tamaño del nuevo dataframe
df.shape
Out[80]:
(23090, 28)

Conteo de valores únicos por columna:

In [81]:
df_espanol.nunique()
Out[81]:
Pago                           4
DiasEnvio(Real)                7
DiasEnvio(Programado)          4
BeneficioPorPedido          8792
EstadoEntrega                  4
RiesgoEntregaTardia            2
Categoria                     31
PaisCliente                    2
IDCliente                   5714
SegmentoCliente                3
PaisPedido                     3
FechaPedido                 7687
IDPedido                    7687
IDArticuloPedido           23090
PrecioArticuloPedido          50
CantidadArticulosPedido        5
Ventas                       164
TotalArticulosPedido        1575
GananciaPorPedido           8792
RegionPedido                   2
DestinoPedido                 76
EstadoPedido                   9
IDProducto                    87
CategoriaProducto             32
NombreProducto                87
PrecioProducto                50
FechaEnvio                  7582
ModoEnvio                      4
dtype: int64

Verificar si existen filas duplicadas o espacios vacios.

In [82]:
# verificar filas duplicadas
duplicados=df_espanol[df.duplicated()]
if duplicados.empty:
    print("No hay filas duplicadas en el DataFrame.")
else:
    print("Las siguientes filas están duplicadas:")
    print(duplicados)
No hay filas duplicadas en el DataFrame.
In [83]:
# verificar espacios vacios
hay_vacios = df_espanol.isna().any().any()

if hay_vacios:
    print("El DataFrame contiene valores vacíos.")
else:
    print("El DataFrame no contiene valores vacíos.")
El DataFrame no contiene valores vacíos.
In [84]:
# FIN DE LA PRIMERA PARTE: Exploración Inicial de Datos
In [85]:
# 2 PARTE: ANALISIS UNIVARIADO

Análisis Univariado:

Distribución de Variables: Realizar un análisis de las variables individuales para entender su distribución. Utilizar histogramas, boxplots y estadísticas descriptivas (media, mediana, desviación estándar, etc.) para las variables numéricas. Para las variables categóricas, calcular frecuencias y proporciones.
Identificación de Outliers: Detectar posibles outliers en las variables numéricas utilizando técnicas como el análisis de boxplots o el cálculo del z-score.

In [86]:
# VER LOS VALORES DE UNA VARIABLE 
df_espanol.Categoria.unique()
Out[86]:
array(["Women's Apparel", 'Shop By Sport', 'Electronics',
       'Baseball & Softball', 'Cardio Equipment', 'Boxing & MMA',
       'Cleats', "Girls' Apparel", 'Accessories', 'Golf Balls',
       'Trade-In', 'Hockey', 'Camping & Hiking', 'Fishing',
       "Men's Footwear", 'Soccer', 'Fitness Accessories',
       "Kids' Golf Clubs", 'Tennis & Racquet', 'Lacrosse',
       'Hunting & Shooting', 'As Seen on  TV!', 'Strength Training',
       'Golf Gloves', 'Golf Bags & Carts', 'Golf Shoes', 'Golf Apparel',
       "Women's Golf Clubs", "Men's Golf Clubs", 'Water Sports',
       'Indoor/Outdoor Games'], dtype=object)

Analisis de algunas variables del dataframe¶

Valores de Pago

In [87]:
df_espanol.Pago.unique()
Out[87]:
array(['PAYMENT', 'TRANSFER', 'DEBIT', 'CASH'], dtype=object)

Valores de Modo de Envio

In [88]:
df_espanol.ModoEnvio.unique()
Out[88]:
array(['Second Class', 'Standard Class', 'First Class', 'Same Day'],
      dtype=object)

Valores de Segmento de Clientes

In [89]:
df_espanol.SegmentoCliente.unique()
Out[89]:
array(['Home Office', 'Consumer', 'Corporate'], dtype=object)

Valores de Estado de Entrega

In [90]:
df_espanol.EstadoEntrega.unique()
Out[90]:
array(['Late delivery', 'Shipping on time', 'Advance shipping',
       'Shipping canceled'], dtype=object)
In [91]:
#EXPLORAMOS LOS DATOS:
#Obtenemos estadísticas descriptivas sobre las columnas numéricas del conjunto de datos:
In [92]:
df_espanol.describe()
Out[92]:
DiasEnvio(Real) DiasEnvio(Programado) BeneficioPorPedido RiesgoEntregaTardia IDCliente IDPedido IDArticuloPedido CantidadArticulosPedido IDProducto CategoriaProducto
count 23090.000000 23090.000000 2.309000e+04 23090.000000 23090.000000 23090.000000 23090.000000 23090.000000 23090.000000 23090.000000
mean 3.532395 2.957687 2.337699e+09 0.544651 6239.185881 31248.316544 78148.127934 2.182763 664.433911 30.279385
std 1.628313 1.354260 3.819456e+09 0.498013 3574.207795 25789.096724 64514.324265 1.471115 309.893562 13.687618
min 0.000000 0.000000 -9.984000e+09 0.000000 3.000000 1.000000 1.000000 1.000000 19.000000 2.000000
25% 2.000000 2.000000 7.050000e+01 0.000000 3184.000000 5498.000000 13714.250000 1.000000 403.000000 18.000000
50% 3.000000 4.000000 1.966500e+09 1.000000 6194.000000 51386.000000 128407.500000 1.000000 627.000000 29.000000
75% 5.000000 4.000000 4.963000e+09 1.000000 9299.500000 56713.750000 141840.750000 3.000000 1004.000000 45.000000
max 6.000000 4.000000 9.999000e+09 1.000000 12434.000000 61584.000000 153996.000000 5.000000 1073.000000 48.000000
In [93]:
# Para cada COLUMNA NUMERICA DE INTERES calcular la mediana, MEDIA Y DESVIACION ESTANDAR
# EJEMPLO PARA Benefit per order Y PRECIO DE PRODUCTO
In [94]:
# el precio del producto tiene valores vacios...ademas hay que convertirlo porque esta en formato Object..a numerico para hacer calculos
In [95]:
import re
import pandas as pd

def clean_price(price_str):
    if pd.isna(price_str):
        return None
    
    # Convertir a string si no lo es
    price_str = str(price_str)
    
    # Eliminar espacios en blanco y caracteres no numéricos excepto punto y coma
    cleaned = re.sub(r'[^\d.,]', '', price_str)
    
    # Reemplazar coma por punto si hay más de un punto (asumiendo que la coma es el separador decimal)
    if cleaned.count('.') > 1 and ',' in cleaned:
        cleaned = cleaned.replace(',', '.')
    
    # Si hay más de un punto, asumimos que todos menos el último son separadores de miles
    parts = cleaned.split('.')
    if len(parts) > 2:
        integer_part = ''.join(parts[:-1])
        decimal_part = parts[-1]
        cleaned = f"{integer_part}.{decimal_part}"
    
    try:
        return float(cleaned)
    except ValueError:
        print(f"No se pudo convertir: {price_str}")
        return None

# Aplicar la función a la columna 'Product Price' y mostrar los resultados
df_espanol['Clean Price'] = df['PrecioProducto'].apply(clean_price)

# Mostrar filas donde la limpieza falló
failed_conversions = df[df['PrecioProducto'].isna()]
print("Filas donde la conversión falló:")
print(failed_conversions[['PrecioProducto', 'Clean Price']])

# Calcular la mediana de los precios limpios
median_prices = df.groupby('Categoria')['Clean Price'].median()
print("\nMediana de precios de productos segun categoria:")
print(median_prices)

# Calcular la media de los precios limpios
media_prices = df.groupby('Categoria')['Clean Price'].mean()
print("\nMedia de precios  de productos segun categoria:")
print(media_prices)
# Calcular la desviacion estandar de los precios limpios
std_prices = df.groupby('Categoria')['Clean Price'].std()
print("\nDesviacion estandar de productos segun categoria:")
print(std_prices)

# Mostrar estadísticas de la columna de precios limpios
print("\nEstadísticas de la columna de precio de productos:")
print(df['Clean Price'].describe())
Filas donde la conversión falló:
Empty DataFrame
Columns: [PrecioProducto, Clean Price]
Index: []

Mediana de precios de productos segun categoria:
Categoria
Accessories             2498999.977
As Seen on  TV!         9998999.786
Baseball & Softball     3499000.168
Boxing & MMA            8998999.786
Camping & Hiking         299980.011
Cardio Equipment        9998999.786
Cleats                  5999000.168
Electronics             3198999.977
Fishing                  399980.011
Fitness Accessories     3499000.168
Girls' Apparel               70.000
Golf Apparel            1998999.977
Golf Bags & Carts       1699900.055
Golf Balls              1798999.977
Golf Gloves             3999000.168
Golf Shoes                   80.000
Hockey                       22.000
Hunting & Shooting      2998999.977
Indoor/Outdoor Games    4997999.954
Kids' Golf Clubs        1999900.055
Lacrosse                2498999.977
Men's Footwear          1299900.055
Men's Golf Clubs        1324900.055
Shop By Sport           3999000.168
Soccer                  7998999.786
Strength Training           189.000
Tennis & Racquet        4499000.168
Trade-In                1598999.977
Water Sports            1999900.055
Women's Apparel              50.000
Women's Golf Clubs      7998999.786
Name: Clean Price, dtype: float64

Media de precios  de productos segun categoria:
Categoria
Accessories             2.499000e+06
As Seen on  TV!         9.999000e+06
Baseball & Softball     4.362567e+06
Boxing & MMA            7.405708e+06
Camping & Hiking        2.999800e+05
Cardio Equipment        9.753777e+06
Cleats                  5.999000e+06
Electronics             3.986990e+06
Fishing                 3.999800e+05
Fitness Accessories     3.499000e+06
Girls' Apparel          1.312678e+06
Golf Apparel            1.721369e+06
Golf Bags & Carts       1.699900e+06
Golf Balls              1.774500e+06
Golf Gloves             5.901723e+06
Golf Shoes              8.122826e+01
Hockey                  2.342308e+01
Hunting & Shooting      2.346087e+06
Indoor/Outdoor Games    4.998000e+06
Kids' Golf Clubs        5.153402e+06
Lacrosse                4.604263e+06
Men's Footwear          1.299900e+06
Men's Golf Clubs        2.857235e+06
Shop By Sport           3.879653e+06
Soccer                  5.839288e+06
Strength Training       1.890000e+02
Tennis & Racquet        4.499000e+06
Trade-In                1.899081e+06
Water Sports            1.999900e+06
Women's Apparel         5.000000e+01
Women's Golf Clubs      6.459881e+06
Name: Clean Price, dtype: float64

Desviacion estandar de productos segun categoria:
Categoria
Accessories             0.000000e+00
As Seen on  TV!         0.000000e+00
Baseball & Softball     1.615250e+06
Boxing & MMA            1.902672e+06
Camping & Hiking        0.000000e+00
Cardio Equipment        1.547033e+06
Cleats                  0.000000e+00
Electronics             9.034617e+05
Fishing                 0.000000e+00
Fitness Accessories     0.000000e+00
Girls' Apparel          1.885016e+06
Golf Apparel            3.644281e+05
Golf Bags & Carts       0.000000e+00
Golf Balls              2.190655e+05
Golf Gloves             3.338846e+06
Golf Shoes              1.795299e+01
Hockey                  1.507722e+00
Hunting & Shooting      1.038113e+06
Indoor/Outdoor Games    0.000000e+00
Kids' Golf Clubs        4.335915e+06
Lacrosse                3.400022e+06
Men's Footwear          0.000000e+00
Men's Golf Clubs        3.413800e+06
Shop By Sport           6.421471e+05
Soccer                  3.213214e+06
Strength Training       0.000000e+00
Tennis & Racquet        0.000000e+00
Trade-In                3.393157e+05
Water Sports            0.000000e+00
Women's Apparel         0.000000e+00
Women's Golf Clubs      3.646446e+06
Name: Clean Price, dtype: float64

Estadísticas de la columna de precio de productos:
count    2.309000e+04
mean     3.035057e+06
std      2.934299e+06
min      2.200000e+01
25%      3.999800e+05
50%      1.999900e+06
75%      4.998000e+06
max      9.999000e+06
Name: Clean Price, dtype: float64
In [96]:
import re
import pandas as pd

def clean_Beneficio_por_pedido(benPP_str):
    if pd.isna(benPP_str):
        return None
    
    # Convertir a string si no lo es
    benPP_str = str(benPP_str)
    
    # Eliminar espacios en blanco y caracteres no numéricos excepto punto y coma
    cleaned = re.sub(r'[^\d.,]', '', benPP_str)
    
    # Reemplazar coma por punto si hay más de un punto (asumiendo que la coma es el separador decimal)
    if cleaned.count('.') > 1 and ',' in cleaned:
        cleaned = cleaned.replace(',', '.')
    
    # Si hay más de un punto, asumimos que todos menos el último son separadores de miles
    parts = cleaned.split('.')
    if len(parts) > 2:
        integer_part = ''.join(parts[:-1])
        decimal_part = parts[-1]
        cleaned = f"{integer_part}.{decimal_part}"
    
    try:
        return float(cleaned)
    except ValueError:
        print(f"No se pudo convertir: {benPP_str}")
        return None

# Aplicar la función a la columna 'Benefit per order' y mostrar los resultados
df['clean_Beneficio_por_pedido'] = df['BeneficioPorPedido'].apply(clean_Beneficio_por_pedido)

# Mostrar filas donde la limpieza falló
failed_conversions = df[df['clean_Beneficio_por_pedido'].isna()]
print("Filas donde la conversión falló:")
print(failed_conversions[['BeneficioPorPedido', 'clean_Beneficio_por_pedido']])

# Calcular la mediana -Beneficio por orden limpio
median_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].median()
print("\nMediana de precios por producto:")
print(median_prices)
# Calcular la media -Beneficio por orden limpio
media_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].mean()
print("\nMedia de precios  de productos segun categoria:")
print(media_prices)
# Calcular la desviacion estandar -Beneficio por orden limpio
std_prices = df.groupby('IDPedido')['clean_Beneficio_por_pedido'].std()
print("\nDesviacion estandar de productos segun categoria:")
print(std_prices)

# Mostrar estadísticas de la columna de precios limpios
print("\nEstadísticas de la columna Beneficio por Pedido:")
print(df['clean_Beneficio_por_pedido'].describe())
Filas donde la conversión falló:
Empty DataFrame
Columns: [BeneficioPorPedido, clean_Beneficio_por_pedido]
Index: []

Mediana de precios por producto:
IDPedido
1        8.879000e+09
7        4.580000e+09
8        1.499750e+09
9        1.980000e+09
10       1.564000e+09
             ...     
61580    1.161900e+09
61581    5.390000e+09
61582    1.050000e+09
61583    2.910000e+09
61584    2.291000e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64

Media de precios  de productos segun categoria:
IDPedido
1        8.879000e+09
7        4.543167e+09
8        2.614875e+09
9        1.926667e+09
10       1.622400e+09
             ...     
61580    2.498520e+09
61581    5.390000e+09
61582    9.414667e+08
61583    3.126233e+09
61584    2.846750e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64

Desviacion estandar de productos segun categoria:
IDPedido
1                 NaN
7        3.315404e+09
8        3.198542e+09
9        1.900561e+09
10       1.079475e+09
             ...     
61580    3.619780e+09
61581    5.232589e+08
61582    8.921650e+08
61583    1.335544e+09
61584    3.036507e+09
Name: clean_Beneficio_por_pedido, Length: 7687, dtype: float64

Estadísticas de la columna Beneficio por Pedido:
count    2.309000e+04
mean     3.543691e+09
std      2.737705e+09
min      0.000000e+00
25%      1.329900e+09
50%      2.886000e+09
75%      5.481000e+09
max      9.999000e+09
Name: clean_Beneficio_por_pedido, dtype: float64
In [97]:
#histogramas, boxplots -valores atipicos
In [98]:
def create_boxplots_and_percentiles(df, columns):
    # Verificar si las columnas existen en el DataFrame
    for col in columns:
        if col not in df_espanol.columns:
            raise ValueError(f"La columna '{col}' no existe en el DataFrame")

    # Crear subplots
    fig = make_subplots(rows=len(columns), cols=1, 
                        subplot_titles=[f'Boxplot de {col}' for col in columns],
                        vertical_spacing=0.1)

    # Crear un boxplot para cada columna especificada
    for i, col in enumerate(columns, 1):
        fig.add_trace(
            go.Box(y=df_espanol[col], name=col, boxpoints='outliers'),
            row=i, col=1
        )

    # Actualizar el diseño
    fig.update_layout(height=300*len(columns), width=800, showlegend=False,
                      title_text="Boxplots de ventas y precio")

    # Mostrar el gráfico
    fig.show()

    # Calcular y mostrar percentiles
    print("Percentiles para ventas y precio:")
    for col in columns:
        percentiles = df_espanol[col].describe(percentiles=[.01, .25, .5, .75, .99])
        print(f"\n{col}:")
        print(percentiles)

# Usar la función
columns_to_analyze = ["DiasEnvio(Real)","DiasEnvio(Programado)","Ventas", "PrecioProducto","BeneficioPorPedido","CantidadArticulosPedido"]
try:
    create_boxplots_and_percentiles(df, columns_to_analyze)
except ValueError as e:
    print(f"Error: {e}")
    print("Columnas disponibles en el DataFrame:")
    print(df.columns.tolist())
Percentiles para ventas y precio:

DiasEnvio(Real):
count    23090.000000
mean         3.532395
std          1.628313
min          0.000000
1%           0.000000
25%          2.000000
50%          3.000000
75%          5.000000
99%          6.000000
max          6.000000
Name: DiasEnvio(Real), dtype: float64

DiasEnvio(Programado):
count    23090.000000
mean         2.957687
std          1.354260
min          0.000000
1%           0.000000
25%          2.000000
50%          4.000000
75%          4.000000
99%          4.000000
max          4.000000
Name: DiasEnvio(Programado), dtype: float64

Ventas:
count             23090
unique              164
top       1.299.900.055
freq               2992
Name: Ventas, dtype: object

PrecioProducto:
count             23090
unique               50
top       5.999.000.168
freq               3251
Name: PrecioProducto, dtype: object

BeneficioPorPedido:
count    2.309000e+04
mean     2.337699e+09
std      3.819456e+09
min     -9.984000e+09
1%      -8.645760e+09
25%      7.050000e+01
50%      1.966500e+09
75%      4.963000e+09
99%      9.730000e+09
max      9.999000e+09
Name: BeneficioPorPedido, dtype: float64

CantidadArticulosPedido:
count    23090.000000
mean         2.182763
std          1.471115
min          1.000000
1%           1.000000
25%          1.000000
50%          1.000000
75%          3.000000
99%          5.000000
max          5.000000
Name: CantidadArticulosPedido, dtype: float64

image.png image-2.png image-3.png image-4.png image-5.png image-6.png

Graficas¶

In [99]:
#Numero de pedidos y tiempo de entrega real
dias_entrega_real=df_espanol.groupby(['DiasEnvio(Real)'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='DiasEnvio(Real)', y='Numero de Pedidos'  , color='DiasEnvio(Real)',
      )
fig.show()

image.png

In [100]:
##Numero de pedidos y tiempo de entrega programado
dias_entrega_real=df_espanol.groupby(['DiasEnvio(Programado)'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='DiasEnvio(Programado)', y='Numero de Pedidos'  , color='DiasEnvio(Programado)'
      )
fig.show()

image.png

In [101]:
#Frecuencia de productos
dias_entrega_real=df_espanol.groupby(['NombreProducto'])['IDProducto'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='NombreProducto', y='Numero de Pedidos'  , color='NombreProducto'
      )
fig.show()

image.png

In [102]:
#Cantidad de pedidos segun categoria
dias_entrega_real=df_espanol.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='Numero de Pedidos'  , color='Categoria'
      )
fig.show()

image.png

In [103]:
#Cantidad de productos segun categoria
dias_entrega_real=df_espanol.groupby(['Categoria'])['IDProducto'].count().reset_index(name='cantidad de productos').sort_values(by= 'cantidad de productos', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='cantidad de productos'  , color='Categoria'
      )
fig.show()

image.png

In [104]:
# Ventas segun categoria de producto
# Aplicar la función anterior para formatear la columna 'Ventas' y mostrar los resultados
df_espanol['Ventas'] = df_espanol['Ventas'].apply(clean_Beneficio_por_pedido)
In [105]:
#dividimos el valor para poder graficar
df_espanol['Ventas1'] = df_espanol['Ventas']/100000
In [106]:
#Graficar
dias_entrega_real=df_espanol.groupby(['Categoria'])['Ventas1'].sum().reset_index(name='Total ventas').sort_values(by= 'Total ventas', ascending= False)
fig=px.bar(dias_entrega_real, x='Categoria', y='Total ventas'  , color='Categoria'
      )
fig.show()

image.png

In [107]:
##estado de las ordenes (segun pais) - se discrimina por el estado de la orden
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'PaisPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders'  , color='PaisPedido',
      )
fig.show()

image.png

In [108]:
#estado de las ordenes segun region - discriminado por estado de las ordenes
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'RegionPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders'  , color='RegionPedido',
      )
fig.show()

image.png

In [109]:
#Estado de pedido segun el pais cliente
data_delivery_status_region=df_espanol.groupby(['EstadoPedido', 'PaisCliente'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoPedido', y='Number of Orders'  , color='PaisCliente',
      )
fig.show()

image.png

In [110]:
#Estado de envios segun el pais
data_delivery_status_region=df_espanol.groupby(['EstadoEntrega', 'PaisPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoEntrega', y='Number of Orders'  , color='PaisPedido',
      )
fig.show()

image.png

In [111]:
#Estado de envios segun region
data_delivery_status_region=df_espanol.groupby(['EstadoEntrega', 'RegionPedido'])['IDPedido'].count().reset_index(name='Number of Orders').sort_values(by= 'Number of Orders', ascending= False)
fig=px.bar(data_delivery_status_region, x='EstadoEntrega', y='Number of Orders'  , color='RegionPedido',
      )
fig.show()

image.png

Analisis solo para argentina*

In [112]:
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']

# Ahora realizamos el agrupamiento solo con los datos de Argentina
data_delivery_status_argentina = df_argentina.groupby('EstadoEntrega')['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by='Numero de Pedidos', ascending=False)

# Creamos el gráfico de barras
fig = px.bar(data_delivery_status_argentina,
             x='EstadoEntrega',
             y='Numero de Pedidos',
             title='Estado de Entrega de Pedidos para Argentina')

# Mostramos el gráfico
fig.show()

image.png

In [113]:
#solo para el pais cliente Puerto Rico
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisCliente'] == 'Puerto Rico']

# Ahora realizamos el agrupamiento solo con los datos de Argentina
data_delivery_status_argentina = df_argentina.groupby('EstadoEntrega')['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by='Numero de Pedidos', ascending=False)

# Creamos el gráfico de barras
fig = px.bar(data_delivery_status_argentina,
             x='EstadoEntrega',
             y='Numero de Pedidos',
             title='Estado de los pedidos que iran a Puerto Rico')

# Mostramos el gráfico
fig.show()

image.png

los principales 20 clientes¶

In [114]:
#segun la cantidad de pedidos
df_espanol['Customer_ID_STR']=df_espanol['IDCliente'].astype(str)

data_customers=df_espanol.groupby(['Customer_ID_STR'])['IDCliente'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(data_customers.head(20),x='Numero de Pedidos', y='Customer_ID_STR' , color='Numero de Pedidos'      )
fig.show()

image.png

In [115]:
#segun la cantidad de pedidos de argentina
In [116]:
# Primero, filtramos el DataFrame para incluir solo los datos de Argentina
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']
data_customers=df_argentina.groupby(['Customer_ID_STR'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.bar(data_customers.head(20),x='Numero de Pedidos', y='Customer_ID_STR' , color='Numero de Pedidos'      )
fig.show()

image.png

In [117]:
#20 principales clientes segun las ganancias de todos los pedidos
In [118]:
df_espanol['Customer_ID_STR']=df_espanol['IDCliente'].astype(str)

data_customers_profit=df_espanol.groupby(['Customer_ID_STR'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)
fig=px.bar(data_customers_profit.head(20),x='Ventas1', y='Customer_ID_STR' , color='Ventas1'      )
fig.show()

#LOS VALORES ESTAN DIVIDIDOS POR MILLONES

image.png

Segmento de Clientes¶

In [119]:
#Cantidad de pedidos segun el segmento de clientes
data_Customer_Segment=df_espanol.groupby(['SegmentoCliente'])['IDCliente'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
fig=px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
       width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.D3)
fig.show()

image.png

In [120]:
#Segmento de Clientes para la region de America del sur
df_argentina = df_espanol[df_espanol['RegionPedido'] == 'South America']

data_Customer_Segment=df_argentina.groupby(['SegmentoCliente'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
       width=600 , height=600 , color_discrete_sequence = ["red", "green", "blue", "goldenrod", "magenta"])

image.png

In [121]:
#Customer Segments de cordoba
df_argentina = df_espanol[df_espanol['RegionPedido'] == 'Central America']

data_Customer_Segment=df_argentina.groupby(['SegmentoCliente'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= False)
px.pie(data_Customer_Segment, values='Numero de Pedidos', names= 'SegmentoCliente' , title= 'Numbero de pedidos segun segmento de cliente',
       width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.G10)

image.png

Pedidos por Categorias¶

In [122]:
#Categorias
data_Category_Name=df_espanol.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Category_Name, x='Numero de Pedidos',y = 'Categoria',color ='Numero de Pedidos')

image.png

In [123]:
# categorias para argentina
In [124]:
df_argentina = df_espanol[df_espanol['PaisPedido'] == 'Argentina']
data_Category_Name=df_argentina.groupby(['Categoria'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Category_Name, x='Numero de Pedidos',y = 'Categoria',color ='Numero de Pedidos')

image.png

Caracteristicas geograficas¶

In [125]:
#Segun region
data_Region=df_espanol.groupby(['RegionPedido'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_Region, x='Numero de Pedidos',y = 'RegionPedido',color ='Numero de Pedidos')

image.png

In [126]:
# segun el pais de pedido
data_countries=df_espanol.groupby(['PaisPedido'])['IDPedido'].count().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_countries.head(20), x='Numero de Pedidos',y = 'PaisPedido',color ='Numero de Pedidos')

image.png

In [127]:
#total de ventas por pais
data_countries=df_espanol.groupby(['PaisPedido'])['Ventas1'].sum().reset_index(name='Numero de Pedidos').sort_values(by= 'Numero de Pedidos', ascending= True)
px.bar(data_countries.head(20), x='Numero de Pedidos',y = 'PaisPedido',color ='Numero de Pedidos')

image.png

Confeccionar un mapa¶

In [923]:
df_geo=df_espanol.groupby([ 'RegionPedido', 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)

df_geo
Out[923]:
RegionPedido PaisPedido Ventas
0 Central America Mexico 282077.461240
2 South America Brasil 170193.677838
1 South America Argentina 41405.607661
In [924]:
import pandas as pd
import plotly.express as px

# Asumiendo que ya tienes tu DataFrame 'df_geo'

# Crear el gráfico de coropletas
fig = px.choropleth(df_geo,
                    locationmode='country names',
                    locations='PaisPedido',
                    color='Ventas',
                    hover_name='PaisPedido',
                    color_continuous_scale=px.colors.sequential.Plasma)

# Ajustar el diseño para una mejor visualización
fig.update_layout(
    title_text='Mapa de Ventas por País',
    geo=dict(
        showframe=False,
        showcoastlines=True,
        projection_type='equirectangular'
    )
)

# Mostrar el gráfico
fig.show()

image.png

In [925]:
df_espanol.PaisPedido.unique()
Out[925]:
array(['Brasil', 'Mexico', 'Argentina'], dtype=object)
In [926]:
# Ventas por pais en grafico circular
df_geo=df_espanol.groupby([ 'RegionPedido', 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)

px.pie(df_geo, values='Ventas1', names= 'PaisPedido' , title= 'Number de pedidos por pais',
       width=600 , height=600 , color_discrete_sequence = px.colors.qualitative.G10)

image.png

analisis de ventas¶

In [927]:
# ventas por region
df_sales_country=df_espanol.groupby([ 'RegionPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'RegionPedido',color ='Ventas de pedido')

image.png

In [928]:
#Cantidad de ventas por pais de pedido
df_sales_country=df_espanol.groupby([ 'PaisPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'PaisPedido',color ='Ventas de pedido')
fig.show()

image.png

Productos¶

In [929]:
#Ventas por producto
df_sales_country=df_espanol.groupby([ 'NombreProducto'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_country.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='Ventas de pedido')
fig.show()

image.png

In [930]:
#Productos, estado de entrega y ventas
df_sales_pd=df_espanol.groupby([ 'NombreProducto', 'EstadoEntrega'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
px.bar(df_sales_pd.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='EstadoEntrega')

image.png

In [931]:
#Productos por region y ventas
df_sales_pr=df_espanol.groupby([ 'NombreProducto', 'RegionPedido'])['Ventas1'].sum().reset_index(name='Ventas de pedido').sort_values(by= 'Ventas de pedido', ascending= False)
fig=px.bar(df_sales_pr.head(10), x='Ventas de pedido',y = 'NombreProducto',color ='RegionPedido')
fig.show()

image.png

categorias¶

In [932]:
#Ventas por Categoria
df_sales_pr=df_espanol.groupby([  'Categoria'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
px.bar(df_sales_pr.head(10), x='Ventas',y = 'Categoria',color ='Categoria')

image.png

In [933]:
#Segun el tipo de pago
df_sales_pr=df_espanol.groupby([ 'Pago'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
px.bar(df_sales_pr.head(10), x='Ventas',y = 'Pago',color ='Ventas')

image.png

In [934]:
#Productos, pagos y ventas
df_sales_tp=df_espanol.groupby([ 'NombreProducto','Pago'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_tp.head(100), x='Ventas',y = 'Pago',color ='NombreProducto')
fig.show()

image.png

analisis de ventas segun las fechas - anual, cuatrimestral, mensual¶

In [935]:
import datetime as dt

data_orderdate=df_espanol[['FechaEnvio', 'Ventas1']]
data_orderdate['order_date'] = pd.to_datetime(data_orderdate['FechaEnvio'])
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\1666086263.py:4: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

In [936]:
data_orderdate["Quarter"] = data_orderdate['order_date'].dt.quarter
data_orderdate["Month"] = data_orderdate['order_date'].dt.month
data_orderdate["year"] = data_orderdate['order_date'].dt.year
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:2: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:3: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

In [937]:
data_orderdate["Quarter"] = data_orderdate['order_date'].dt.quarter
data_orderdate["Month"] = data_orderdate['order_date'].dt.month
data_orderdate["year"] = data_orderdate['order_date'].dt.year
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:2: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3482627655.py:3: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

In [938]:
data_orderdate['YearStr']=data_orderdate['year'].astype(str)
df_sales_year=data_orderdate.groupby([ 'YearStr'])['Ventas1'].sum().reset_index(name='Ventas de Pedido').sort_values(by= 'Ventas de Pedido', ascending= False)
fig=px.bar(df_sales_year, x='Ventas de Pedido',y = 'YearStr',color ='Ventas de Pedido')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\712514235.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

image.png

In [939]:
data_orderdate['QuarterStr']=data_orderdate['Quarter'].astype(str)
df_sales_quarter=data_orderdate.groupby([ 'YearStr','QuarterStr'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='Ventas',y = 'QuarterStr',color ='YearStr')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\695585461.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

image.png

In [940]:
data_orderdate['MonthStr']=data_orderdate['Month'].astype(str)
df_sales_m=data_orderdate.groupby([ 'QuarterStr', 'MonthStr'])['Ventas1'].sum().reset_index(name='Ventas1').sort_values(by= 'Ventas1', ascending= False)
fig=px.bar(df_sales_m, x='Ventas1',y = 'QuarterStr',color ='MonthStr')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\1003044912.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

image.png

In [941]:
data_orderdate['YearStr']=data_orderdate['Month'].astype(str)
df_sales_quarter=data_orderdate.groupby([ 'YearStr','Month'])['Ventas1'].sum().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='YearStr',y = 'Ventas',color ='Month')
fig.show()

# ver detalle YearStr
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\2979100799.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

image.png

In [942]:
data_orderdate['YearStr'].unique()
Out[942]:
array(['4', '3', '2', '1', '5', '6'], dtype=object)

#separar la fecha

In [943]:
df_espanol1=df_espanol
# Primero, convertimos la columna a tipo datetime
df_espanol1['FechaEnvio'] = pd.to_datetime(df_espanol1['FechaEnvio'])

# Ahora creamos las nuevas columnas
df_espanol1['dia'] = df_espanol1['FechaEnvio'].dt.day
df_espanol1['mes'] = df_espanol1['FechaEnvio'].dt.month
df_espanol1['anio'] = df_espanol1['FechaEnvio'].dt.year


# Si quieres que el formato sea exactamente como 1-18-2018, puedes hacer:
df_espanol1['fecha_formateada'] = df_espanol1['FechaEnvio'].dt.strftime('%d-%m-%Y')
In [944]:
data_orderdate['YearStr']=data_orderdate['Month'].astype(str)
df_sales_quarter=df_espanol1.groupby([ 'anio','mes'])['Ventas1'].count().reset_index(name='Ventas').sort_values(by= 'Ventas', ascending= False)
fig=px.bar(df_sales_quarter, x='anio',y = 'Ventas',color ='Ventas')
fig.show()
C:\Users\Usuario\AppData\Local\Temp\ipykernel_18968\3745632177.py:1: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

image.png

Analaisis de Pedidos segun el año¶

In [950]:
import pandas as pd
import plotly.graph_objects as go

#  'tendencias'
# y tiene las columnas 'PaisPedido', 'anio', y 'IDPedido'
# Calcular la producción total por año y Provincia
tendencias = df_espanol.groupby(['PaisPedido','anio'])['IDPedido'].count().reset_index()

# Crear una figura
fig = go.Figure()

# Iterar a través de países únicos
for pais in tendencias['PaisPedido'].unique():
    # Filtrar datos para el país actual
    data_pais = tendencias[tendencias['PaisPedido'] == pais]
    
    # Agregar una línea para cada país
    fig.add_trace(go.Scatter(
        x=data_pais['anio'],
        y=data_pais['IDPedido'],
        mode='lines',
        name=pais
    ))

# Personalizar el diseño del gráfico
fig.update_layout(
    title='Tendencias en pedidos por Años',
    xaxis_title='Año',
    yaxis_title='Cantidad de Pedidos',
    legend_title_text='País',
    legend=dict(
        yanchor="top",
        y=0.99,
        xanchor="left",
        x=0.01
    )
)

# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)

# Mostrar el gráfico
fig.show()

image.png

In [952]:
df_espanol['PrecioProducto'] = df_espanol['PrecioProducto'].apply(clean_Beneficio_por_pedido)
df_espanol['Precio2'] = df_espanol['PrecioProducto']/1000
In [954]:
#CANTIDAD DE PEDIDOS POR AÑO SEGUN EL PRODUCTO
In [955]:
import pandas as pd
import plotly.graph_objects as go
# Calcular region, año
tendencias = df_espanol.groupby(['RegionPedido','anio'])['IDPedido'].count().reset_index()
# 'tendencias'
# y tiene las columnas 'PaisRegion', 'anio', y 'IDPedido'

# Crear una figura
fig = go.Figure()

# Iterar a través de países únicos
for pais in tendencias['RegionPedido'].unique():
    # Filtrar datos para el país actual
    data_pais = tendencias[tendencias['RegionPedido'] == pais]
    
    # Agregar una línea para cada país
    fig.add_trace(go.Scatter(
        x=data_pais['anio'],
        y=data_pais['IDPedido'],
        mode='lines',
        name=pais
    ))

# Personalizar el diseño del gráfico
fig.update_layout(
    title='Tendencias en pedidos por Años',
    xaxis_title='Año',
    yaxis_title='Cantidad de Pedidos',
    legend_title_text='País',
    legend=dict(
        yanchor="top",
        y=0.99,
        xanchor="left",
        x=0.01
    )
)

# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)

# Mostrar el gráfico
fig.show()

image.png

In [957]:
import pandas as pd
import plotly.graph_objects as go

# Asumiendo que tu DataFrame se llama 'tendencias'
# y tiene las columnas 'Producto', 'anio', y 'IDPedido'

tendencias = df_espanol.groupby(['NombreProducto','anio'])['IDPedido'].count().reset_index()
# Crear una figura
fig = go.Figure()

# Iterar a través de países únicos
for pais in tendencias['NombreProducto'].unique():
    # Filtrar datos para el país actual
    data_pais = tendencias[tendencias['NombreProducto'] == pais]
    
    # Agregar una línea para cada país
    fig.add_trace(go.Scatter(
        x=data_pais['anio'],
        y=data_pais['IDPedido'],
        mode='lines',
        name=pais
    ))

# Personalizar el diseño del gráfico
fig.update_layout(
    title='Tendencias en pedidos por Años',
    xaxis_title='Año',
    yaxis_title='Cantidad de Pedidos',
    legend_title_text='País',
    legend=dict(
        yanchor="top",
        y=0.99,
        xanchor="left",
        x=0.01
    )
)

# Agregar líneas de cuadrícula
fig.update_xaxes(showgrid=True)
fig.update_yaxes(showgrid=True)

# Mostrar el gráfico
fig.show()

image.png

Mapa de Calor de Variables numericas¶

In [958]:
# Excluir columnas no numéricas
numeric_df_espanol = df_espanol.select_dtypes(include=[np.number])

# Crear el mapa de calor de correlación
plt.figure(figsize=(16, 6))
heatmap = sns.heatmap(numeric_df_espanol.corr(), annot=True, cmap='BrBG')
heatmap.set_title('Mapa de calor de correlación', fontdict={'fontsize': 18}, pad=12)
plt.show()

image.png

Grafico de dispersión para observar la relación entre "PrecioProducto" y "Ventas"¶

In [959]:
# Elegir las dos columnas numéricas que deseas comparar
columna_x = 'PrecioProducto'
columna_y = 'Ventas1'

# Crear el gráfico de dispersión
plt.figure(figsize=(10, 6))
plt.scatter(df_espanol[columna_x], df_espanol[columna_y], alpha=0.5, color='blue')
plt.title(f'Gráfico de Dispersión entre {columna_x} y {columna_y}')
plt.xlabel(columna_x)
plt.ylabel(columna_y)
plt.grid(True)
plt.show()

image.png

In [ ]:
 
In [ ]:

In [ ]:

In [ ]:
 
In [ ]: